package cn.easier.activity.console.utils;

import java.beans.PropertyDescriptor;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

public class ExcelUtil {

    /**
     * 导出
     *
     * @param response
     * @param fileName   导出的文件名称
     * @param datas      导出的数据
     * @param properties 实体名-列明
     */
    public static void downloadExcel(HttpServletResponse response,
                                     String fileName, List<?> datas, List<Map<String, String>> properties) {
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ServletOutputStream out = response.getOutputStream();

            ExcelUtil.createWorkBook(properties, datas).write(os);
            byte[] content = os.toByteArray();
            InputStream is = new ByteArrayInputStream(content);
            // 设置response参数，可以打开下载页面
            response.reset();
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename="
                    + new String((fileName + ".xls").getBytes(), "iso-8859-1"));

            bis = new BufferedInputStream(is);
            bos = new BufferedOutputStream(out);
            byte[] buff = new byte[2048];
            int bytesRead;
            while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                bos.write(buff, 0, bytesRead);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bis != null)
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            if (bos != null)
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    /**
     * 创建excel
     *
     * @param properties
     * @param datas
     * @return
     * @throws Exception
     */
    public static Workbook createWorkBook(List<Map<String, String>> properties,
                                          List<?> datas) throws Exception {
        // 创建Workbook
        Workbook workbook = new SXSSFWorkbook(60000);
        // 创建Sheet
        Sheet sheet = workbook.createSheet();
        // 创建标题行
        Row titleRow = sheet.createRow(0);

        String field = null;
        String title = null;
        // 取出Bean属性,同时创建Excel标题
        List<String> fields = new ArrayList<String>();
        for (int i = 0; i < properties.size(); i++) {
            Map<String, String> m = properties.get(i);
            for (Map.Entry<String, String> e : m.entrySet()) {
                title = e.getValue();
                field = e.getKey();
                break;
            }
            titleRow.createCell(i).setCellValue(title);
            fields.add(field);
        }
        // 创建数据,从第2行开始
        for (int i = 0; i < datas.size(); i++) {
            Object o = datas.get(i);
            Row rowData = sheet.createRow(i + 1);
            for (int j = 0; j < fields.size(); j++) {
                field = fields.get(j);
                // 获取字段属性值
                Object value = null;
                //导出优惠券无订单信息情况下导出订单属性会报错
                try {
                    value = PropertyUtils.getProperty(o, field);//通过反射读取属性
                } catch (Exception e) {
                    value = "";
                }
                if (value == null) {
                    continue;
                }
                Cell cell = rowData.createCell(j);
                setCellValue(cell, value);
            }
        }
        return workbook;
    }

    /**
     * 设置值
     *
     * @param container
     * @param field
     * @param title
     */
    public static void createExcelField(List<Map<String, String>> container,
                                        String field, String title) {
        Map<String, String> map = new HashMap<String, String>();
        map.put(field.trim(), title.trim());
        container.add(map);
    }

    /**
     * 设置Cell单元的值
     *
     * @param cell
     * @param value
     */
    private static void setCellValue(Cell cell, Object value) {
        if (value instanceof Number) {
            Double numberVal = (Double) ConvertUtils.convert(value,
                    Double.class);
            cell.setCellValue(numberVal);
        } else if (value instanceof Date) {
            Date date = (Date) value;
            // 日期默认转型
            String dateTimeVal = DateUtil
                    .date2Str(
                            date,
                            DateUtil.DEFAULT_DATE_TIME_FORMAT);
            // 是否为日期格式
            int idf = dateTimeVal.lastIndexOf("00:00:00");
            if (idf != -1) {
                String dateVal = DateUtil
                        .date2Str(
                                date,
                                DateUtil.DEFAULT_DATE_FORMAT);
                cell.setCellValue(dateVal);
            } else {
                cell.setCellValue(dateTimeVal);
            }
        } else {
            cell.setCellValue(value.toString());
        }
    }

    /**
     * 得到Workbook对象
     *
     * @param file
     * @return
     * @throws IOException
     */
    public static Workbook getWorkBook(MultipartFile file) throws IOException {
        //这样写  excel 能兼容03和07
        InputStream is = file.getInputStream();
        Workbook workBook = null;
        try {
            workBook = new HSSFWorkbook(is);
        } catch (Exception ex) {
            is = file.getInputStream();
            workBook = new XSSFWorkbook(is);
        }
        return workBook;
    }

    /**
     * 得到错误信息
     *
     * @param sb
     * @param list
     * @param i
     * @param obj
     * @param name 用哪个属性名去表明不和规定的数据
     * @param msg
     * @throws Exception
     */
    public static void getWrongInfo(StringBuilder sb, List list, int i, Object obj, String name, String msg) throws Exception {
        Class clazz = obj.getClass();
        Object str = null;
        //得到属性名数组
        Field[] fields = clazz.getDeclaredFields();
        for (Field f : fields) {
            if (f.getName().equals(name)) {
                //用来得到属性的get和set方法
                PropertyDescriptor pd = new PropertyDescriptor((String) f.getName(), clazz);
                //得到get方法
                Method getMethod = pd.getReadMethod();
                str = getMethod.invoke(obj);
            }
        }
        if (i == 0)
            sb.append(msg + str + ";");
        else if (i == (list.size() - 1))
            sb.append(str + "</br>");
        else
            sb.append(str + ";");
    }
}
